package com.twd.mynio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

public class MyServer {
    public static List<SelectionKey> list=new ArrayList<>();
    public static  ServerSocketChannel server;
    public static Selector selector;
    public static void main(String[] args) throws IOException, InterruptedException {
        selector = Selector.open();
        server = ServerSocketChannel.open();
        server.configureBlocking(false);
        server.bind(new InetSocketAddress(9988));
        server.register(selector,SelectionKey.OP_ACCEPT,server);

        for (;;){
            if (selector.select()>0){
                handler();
            }else{
                addRegister();
            }
        }
    }

    private static void handler() throws IOException, InterruptedException {
        new Thread(()->{
            try {
            SocketChannel open = SocketChannel.open();
            System.out.println("假设另一个客户端有也需要读事件");
            //TimeUnit.SECONDS.sleep(1);
                open.configureBlocking(false);
                changeRead(open.register(selector,SelectionKey.OP_READ,open));
                System.out.println("=======================");
            } catch (IOException e) {
            e.printStackTrace();
        }
        }).start();
        TimeUnit.SECONDS.sleep(5);
        System.out.println("执行正常逻辑，将客户端channel注册到selector并且是读事件");
        Set<SelectionKey> selectionKeys = selector.selectedKeys();
        Iterator<SelectionKey> iterator = selectionKeys.iterator();
        while (iterator.hasNext()){
            SelectionKey key = iterator.next();
            iterator.remove();
            if (key.isAcceptable()){
                System.out.println("注册");
                ServerSocketChannel channel = (ServerSocketChannel) key.attachment();
                SocketChannel client = channel.accept();
                System.out.println("server_channel"+channel.hashCode());
                System.out.println("client_channel"+client.hashCode());
                client.configureBlocking(false);
                client.register(selector,SelectionKey.OP_READ,client);
            }else if (key.isReadable()){
                System.out.println("读取数据");
                SocketChannel socketChannel= (SocketChannel) key.channel();
                ByteBuffer allocate = ByteBuffer.allocate(1024);
                socketChannel.read(allocate);
                System.out.println(allocate.toString());
//                changeRead(key);
            }else {
                System.out.println("写时间");
                SocketChannel socketChannel= (SocketChannel) key.channel();
                System.out.println(socketChannel.hashCode());
                ByteBuffer allocate = ByteBuffer.allocate(1024);
                allocate.put("wwwwww".getBytes());
                socketChannel.write(allocate);
                allocate.clear();
                key.cancel();
            }
        }
    }

    public static void addRegister() throws IOException {
        System.out.println("+++++++++++++++++++++++");
        synchronized (list){
            while(list.size()>0){
                System.out.println("转为写事件");
                SelectionKey selectionKey = list.remove(0);
                SocketChannel channel = (SocketChannel) selectionKey.attachment();
                System.out.println(channel.hashCode());
                channel.register(selector,SelectionKey.OP_WRITE,channel);
            }
        }
    }

    public static void changeRead(SelectionKey selectionKey){
        synchronized (list){
            list.add(selectionKey);
        }
        selector.wakeup();
    }
}
